# coding=utf-8
"""
功能：
favicon
静态路由
动态路由指定传参格式
自定义正则路由
自定义状态码
abort函数
errorhandler函数
return函数
redirect函数
url_for函数
cookies状态保持
render_template响应参数传递
app.add_template_filter(FuncName, 'FilterName')
@app.template_filter('FilterName')
FlaskForm类
flash函数
获取表单请求方法数据
macro
include
"""
import os

from flask import Flask, make_response, current_app, abort, redirect, request, url_for, send_from_directory, \
    render_template, flash
from flask_wtf import FlaskForm
from werkzeug.routing import BaseConverter
from flask_script import Manager, Server
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, EqualTo

app = Flask(__name__)
# 设置 secret_key
app.config['SECRET_KEY'] = 'python'
manager = Manager(app)


# 页面 favicon
@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico',
                               mimetype='image/vnd.microsoft.icon')


# 静态路由
@app.route('/')
def hello_world():
    return '<h1>hello world2018</h1>'


# 动态路由指定传参格式
@app.route('/strs/<int:strs>/')
def strs(strs):
    return '<h1>hello %s</h1>' % strs


# 自定义正则类
class Regex(BaseConverter):
    def __init__(self, url, *args):
        super(Regex, self).__init__(url)
        self.regex = args[0]


# 注册自定义正则类
app.url_map.converters['re'] = Regex


# 使用自定义路由访问
@app.route('/re/<re(".*"):file_name>')
def regex(file_name):
    if not file_name:
        file_name = 'cFlaskBase/default.html'
    else:
        file_name = 'cFlaskBase/' + file_name
    resp = make_response(current_app.send_static_file(file_name))
    return resp


# 自定义状态码
@app.route('/resp/')
def resp_status():
    return 'hello response', 666


# abort 函数：抛出符合 http 协议状态码
# 一般配合errorhandler实现自定义错误页面
@app.route('/abort/')
def abort_status():
    abort(405)
    return 'hello abort', 999


# errorhandler 捕获状态码
@app.errorhandler(405)
def errorhandler(e):
    return "请求方法不允许%s" % e


# redirect 重定向: 当项目文件或目录不存在
# redirect 接受 url 链接参数
@app.route('/redir/')
def redirect_handler():
    return redirect('http://www.baidu.com')


# url_for 接受参数为视图函数名
@app.route('/url_for/')
def url_for_handler():
    return redirect(url_for('redirect_handler'))


# 状态保持
# http 协议无状态，减少服务器压力
@app.route('/set_cookies/')
def set_cookies():
    resp = make_response('set_cookies')
    resp.set_cookie('key1', 'value1')
    return resp


# 获取用户 cookies 信息
@app.route('/get_cookies/')
def get_cookies():
    resp = request.cookies.get('key1')
    return resp


# 模板传值
@app.route('/template/')
def template():
    temp = 'nihao'
    ls = [5, 7, 8]
    dic = {"name": 'hehe', "age": 24}
    return render_template('cFlaskBase/template.html', temp=temp, ls=ls, dic=dic)


# 自定义过滤器
def double_filter(ls):
    return ls[::-2]


# 注册自定义过滤器
app.add_template_filter(double_filter, 'db1')


# 自定义过滤器，名称如果和内置过滤器重名，会重写过滤器
@app.template_filter('db2')
def num_filter(ls):
    return ls[::-3]


# 自定义表单
class Form(FlaskForm):
    # 自定义字段类型，加入验证函数，必须有数据存在
    user = StringField(validators=[DataRequired()])
    pswd = PasswordField(validators=[DataRequired()])
    pswd2 = PasswordField(validators=[DataRequired(), EqualTo('pswd2')])
    submit = SubmitField(label=u'注册')


# 获取表单请求方法数据
@app.route('/form/', methods=['GET', 'POST'])
def form_handler():
    form = Form()
    if request.method == 'GET':
        # 实例化表单对象
        if request.args:
            us = request.args.get('user')
            ps = request.args.get('pswd')
            print us, ps
    elif request.method == 'POST':
        # validate_on_submit方法的返回值为布尔类型
        # 调用验证函数，验证页面中是否设置csrf_token
        if form.validate_on_submit():
            # 获取wtf表单数据
            us = request.form.get('user')
            ps = request.form.get('pswd')
            ps2 = request.form.get('pswd2')
            # us = form.user.data
            # ps = form.pswd.data
            # ps2 = form.pswd2.data
            print us, ps, ps2
        else:
            flash(u"请输入用户信息！")
    return render_template('cFlaskBase/form.html', **locals())


# include包含的使用，不能重复wtf表单对象的复用，只能实现html静态页面的内容
@app.route('/include/')
def include():
    return render_template('cFlaskBase/include.html')


def _test_index():
    """
    _test_index()
    >
    python cFlaskBase.py runserver -h 0.0.0.0
    192.168.99.80:5000
    """
    print app.url_map
    app.debug = True
    manager.add_command("runserver", Server())  # 命令是runserver
    manager.run()


if __name__ == '__main__':
    _test_index()
